/**
 * WebRTC 连接管理器
 * 封装 WebRTC 连接的创建、监控和管理
 */

import { getDefaultWebRtcConfig, getSrsApiUrl } from './webrtc-config';
import { validateSdp, ensureBundleAndMid, extractIceCandidates } from './webrtc-sdp';
import { getTokenAsync } from './secure-storage';

export interface IceCandidateInfo {
  candidate: string;
  sdpMLineIndex: number | null;
  sdpMid: string | null;
  type: RTCIceCandidateType;
  protocol: string | null;
  address: string | null;
  port: number | null;
}

export interface ConnectionStats {
  iceConnectionState: RTCIceConnectionState;
  connectionState: RTCPeerConnectionState;
  signalingState: RTCSignalingState;
  iceGatheringState: RTCIceGatheringState;
  localCandidates: IceCandidateInfo[];
  remoteCandidates: string[];
}

export interface ConnectionCallbacks {
  onIceCandidate?: (candidate: IceCandidateInfo) => void;
  onIceCandidateComplete?: (candidates: IceCandidateInfo[]) => void;
  onIceConnectionStateChange?: (state: RTCIceConnectionState) => void;
  onConnectionStateChange?: (state: RTCPeerConnectionState) => void;
  onIceGatheringStateChange?: (state: RTCIceGatheringState) => void;
  onTrack?: (event: RTCTrackEvent) => void;
  onError?: (error: Error) => void;
}

/**
 * WebRTC 连接管理器类
 */
export class WebRtcConnectionManager {
  private pc: RTCPeerConnection;
  private iceCandidates: IceCandidateInfo[] = [];
  private callbacks: ConnectionCallbacks;
  private streamName: string;
  private isVoiceOnly: boolean;

  constructor(
    streamName: string,
    isVoiceOnly: boolean = false,
    callbacks: ConnectionCallbacks = {},
    config?: RTCConfiguration
  ) {
    this.streamName = streamName;
    this.isVoiceOnly = isVoiceOnly;
    this.callbacks = callbacks;
    this.pc = new RTCPeerConnection(config || getDefaultWebRtcConfig());
    this.setupEventListeners();
  }

  /**
   * 设置事件监听器
   */
  private setupEventListeners(): void {
    // ICE 候选收集
    this.pc.onicecandidate = (event) => {
      if (event.candidate) {
        const candidateInfo: IceCandidateInfo = {
          candidate: event.candidate.candidate,
          sdpMLineIndex: event.candidate.sdpMLineIndex,
          sdpMid: event.candidate.sdpMid,
          type: event.candidate.type || 'unknown',
          protocol: event.candidate.protocol,
          address: event.candidate.address,
          port: event.candidate.port,
        };
        this.iceCandidates.push(candidateInfo);
        this.callbacks.onIceCandidate?.(candidateInfo);
      } else {
        this.callbacks.onIceCandidateComplete?.(this.iceCandidates);
      }
    };

    // ICE 连接状态变化
    this.pc.oniceconnectionstatechange = () => {
      this.callbacks.onIceConnectionStateChange?.(this.pc.iceConnectionState);
    };

    // 连接状态变化
    this.pc.onconnectionstatechange = () => {
      this.callbacks.onConnectionStateChange?.(this.pc.connectionState);
    };

    // ICE 收集状态变化
    this.pc.onicegatheringstatechange = () => {
      this.callbacks.onIceGatheringStateChange?.(this.pc.iceGatheringState);
    };

    // 远程轨道
    this.pc.ontrack = (event) => {
      this.callbacks.onTrack?.(event);
    };
  }

  /**
   * 添加本地流
   */
  addLocalStream(stream: MediaStream): void {
    stream.getTracks().forEach(track => {
      this.pc.addTrack(track, stream);
    });
  }

  /**
   * 添加 transceiver（用于拉流）
   */
  addTransceivers(): void {
    this.pc.addTransceiver('audio', { direction: 'recvonly' });
    if (!this.isVoiceOnly) {
      this.pc.addTransceiver('video', { direction: 'recvonly' });
    }
  }

  /**
   * 创建并处理 offer
   */
  async createOffer(options?: RTCOfferOptions): Promise<RTCSessionDescriptionInit> {
    console.log('🔧 [WebRTC Manager] 创建 offer, 流名称:', this.streamName);
    console.log('🔧 [WebRTC Manager] Offer 选项:', options);
    console.log('🔧 [WebRTC Manager] 当前连接状态:', {
      signalingState: this.pc.signalingState,
      iceConnectionState: this.pc.iceConnectionState,
      iceGatheringState: this.pc.iceGatheringState,
    });
    
    const offer = await this.pc.createOffer(options);
    console.log('🔧 [WebRTC Manager] Offer 创建成功:', {
      type: offer.type,
      sdpLength: offer.sdp?.length || 0,
    });
    
    await this.pc.setLocalDescription(offer);
    console.log('🔧 [WebRTC Manager] 本地描述已设置, 状态:', this.pc.signalingState);

    // 确保 SDP 包含 BUNDLE 和 mid
    const localSdp = this.pc.localDescription?.sdp || offer.sdp;
    const { sdp: modifiedSdp, modified } = ensureBundleAndMid(localSdp);

    if (modified) {
      console.log('🔧 [WebRTC Manager] SDP 已修改 (添加 BUNDLE/mid)');
      const modifiedOffer = new RTCSessionDescription({
        type: 'offer',
        sdp: modifiedSdp,
      });
      await this.pc.setLocalDescription(modifiedOffer);
      console.log('🔧 [WebRTC Manager] 修改后的本地描述已设置');
    }

    const finalOffer = this.pc.localDescription || offer;
    console.log('🔧 [WebRTC Manager] 最终 offer:', {
      type: finalOffer.type,
      sdpLength: finalOffer.sdp?.length || 0,
      signalingState: this.pc.signalingState,
    });
    
    return finalOffer;
  }

  /**
   * 设置远程描述
   */
  async setRemoteDescription(description: RTCSessionDescriptionInit): Promise<void> {
    console.log('🔧 [WebRTC Manager] 设置远程描述, 流名称:', this.streamName);
    console.log('🔧 [WebRTC Manager] 远程描述类型:', description.type);
    console.log('🔧 [WebRTC Manager] 远程描述 SDP 长度:', description.sdp?.length || 0);
    console.log('🔧 [WebRTC Manager] 设置前连接状态:', {
      signalingState: this.pc.signalingState,
      iceConnectionState: this.pc.iceConnectionState,
      iceGatheringState: this.pc.iceGatheringState,
    });
    
    // 验证 SDP
    const sdp = typeof description.sdp === 'string' ? description.sdp : '';
    const validation = validateSdp(sdp);
    console.log('🔧 [WebRTC Manager] SDP 验证结果:', {
      isValid: validation.isValid,
      hasBundle: validation.hasBundle,
      hasAudio: validation.hasAudio,
      hasVideo: validation.hasVideo,
      candidateCount: validation.candidateCount,
      errors: validation.errors,
      warnings: validation.warnings,
    });

    if (!validation.isValid) {
      console.error('❌ [WebRTC Manager] SDP 验证失败:', validation.errors);
      throw new Error(`SDP 验证失败: ${validation.errors.join(', ')}`);
    }

    if (validation.warnings.length > 0) {
      console.warn('⚠️ [WebRTC Manager] SDP 警告:', validation.warnings);
    }

    try {
      await this.pc.setRemoteDescription(description);
      console.log('✅ [WebRTC Manager] 远程描述设置成功');
      console.log('🔧 [WebRTC Manager] 设置后连接状态:', {
        signalingState: this.pc.signalingState,
        iceConnectionState: this.pc.iceConnectionState,
        iceGatheringState: this.pc.iceGatheringState,
      });
    } catch (error: any) {
      console.error('❌ [WebRTC Manager] 设置远程描述失败:', error);
      throw new Error(`设置远程描述失败: ${error.message || error}`);
    }
  }

  /**
   * 等待 ICE 连接建立
   */
  async waitForIceConnection(timeout: number = 10000): Promise<boolean> {
    return new Promise((resolve) => {
      const checkConnection = () => {
        const state = this.pc.iceConnectionState;
        if (state === 'connected' || state === 'completed') {
          resolve(true);
        } else if (state === 'failed') {
          // 尝试重启 ICE
          try {
            this.pc.restartIce();
            setTimeout(checkConnection, 2000);
          } catch (e) {
            resolve(false);
          }
        } else if (state === 'disconnected' || state === 'closed') {
          resolve(false);
        } else {
          setTimeout(checkConnection, 200);
        }
      };

      const handler = () => checkConnection();
      this.pc.addEventListener('iceconnectionstatechange', handler);

      setTimeout(() => {
        this.pc.removeEventListener('iceconnectionstatechange', handler);
        if (this.pc.iceConnectionState !== 'connected' && this.pc.iceConnectionState !== 'completed') {
          resolve(false);
        }
      }, timeout);

      checkConnection();
    });
  }

  /**
   * 获取连接统计信息
   */
  getStats(): ConnectionStats {
    return {
      iceConnectionState: this.pc.iceConnectionState,
      connectionState: this.pc.connectionState,
      signalingState: this.pc.signalingState,
      iceGatheringState: this.pc.iceGatheringState,
      localCandidates: this.iceCandidates,
      remoteCandidates: extractIceCandidates(this.pc.remoteDescription?.sdp || ''),
    };
  }

  /**
   * 获取 RTCPeerConnection 实例
   */
  getPeerConnection(): RTCPeerConnection {
    return this.pc;
  }

  /**
   * 关闭连接
   */
  close(): void {
    this.pc.close();
    this.iceCandidates = [];
  }
}

/**
 * 发送 SDP offer 到 SRS（推流）
 */
export async function publishToSrs(
  streamName: string,
  offer: RTCSessionDescriptionInit
): Promise<string> {
  console.log('📤 [WebRTC] 开始推流 SDP 交换');
  console.log('📤 [WebRTC] 流名称:', streamName);
  console.log('📤 [WebRTC] Offer 类型:', offer.type);
  console.log('📤 [WebRTC] Offer SDP 长度:', offer.sdp?.length || 0);
  console.log('📤 [WebRTC] Offer SDP 预览:', offer.sdp?.substring(0, 200) || 'N/A');
  
  const token = await getTokenAsync();
  if (!token) {
    throw new Error('请先登录');
  }

  // 前端只传递必要信息（streamName 和 sdp），由后端构建完整的 SRS 请求体
  // 后端会使用自己的 srs_config 来构建 api、streamurl、app 等字段
  console.log('📤 [WebRTC] 流名称:', streamName);
  console.log('📤 [WebRTC] 后端代理 URL:', getSrsApiUrl('/rtc/v1/publish'));

  const requestBody: any = {
    stream: streamName,  // 只传递流名称，后端会构建其他字段
    sdp: offer.sdp,
  };

  const apiUrl = getSrsApiUrl('/rtc/v1/publish')
  console.log('📤 [WebRTC] 请求体:', {
    stream: requestBody.stream,
    sdpLength: requestBody.sdp?.length || 0,
  });
  console.log('📤 [WebRTC] 准备发送请求到后端:', apiUrl);
  console.log('📤 [WebRTC] 请求方法: POST');
  console.log('📤 [WebRTC] 请求头: Authorization Bearer token');

  const response = await fetch(apiUrl, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
      'Authorization': `Bearer ${token}`,
    },
    body: JSON.stringify(requestBody),
  });

  console.log('📤 [WebRTC] 推流响应状态:', response.status, response.statusText);
  console.log('📤 [WebRTC] 推流响应头:', Object.fromEntries(response.headers.entries()));

  const responseText = await response.text();
  console.log('📤 [WebRTC] 推流响应体长度:', responseText.length);
  console.log('📤 [WebRTC] 推流响应体预览:', responseText.substring(0, 300));
  
  // 检查 HTTP 状态码
  if (!response.ok) {
    // 检查是否是流忙碌错误（5020），提供更详细的错误信息
    let errorMessage = `推流请求失败: ${response.status} ${responseText}`;
    try {
      const errorDetail = JSON.parse(responseText);
      if (errorDetail.code === 5020) {
        errorMessage = `推流连接失败: 流 ${streamName} 忙碌，请稍后重试或使用不同的流名称`;
      } else if (errorDetail.message || errorDetail.msg) {
        errorMessage = `推流连接失败: ${errorDetail.message || errorDetail.msg}`;
      }
    } catch (parseError) {
      // 如果不是 JSON 格式，检查文本内容
      if (responseText.includes('5020') || responseText.includes('stream already exists') || 
          responseText.includes('stream busy') || responseText.includes('RtcStreamBusy')) {
        errorMessage = `推流连接失败: 流 ${streamName} 忙碌，请稍后重试或使用不同的流名称`;
      }
    }
    
    throw new Error(errorMessage);
  }

  // 处理响应
  if (responseText.trim().startsWith('v=')) {
    // SDP 格式响应
    console.log('✅ [WebRTC] 推流 SDP 交换成功 (SDP 格式)');
    console.log('✅ [WebRTC] Answer SDP 长度:', responseText.length);
    console.log('✅ [WebRTC] Answer SDP 预览:', responseText.substring(0, 300));
    return responseText;
  }

  // JSON 格式响应
  const data = JSON.parse(responseText);
  console.log('📤 [WebRTC] 推流响应 JSON:', {
    code: data.code,
    message: data.message || data.msg,
    hasSdp: !!data.sdp,
    sdpLength: data.sdp?.length || 0,
  });
  
  if (data.code !== 0) {
    const errorCode = data.code;
    let errorMsg = data.message || data.msg || `SRS 返回错误码: ${errorCode}`;
    
    // 检查是否是流忙碌错误（5020 或 400 可能是流已存在）
    if (errorCode === 5020 || errorCode === 400) {
      // 检查响应中是否包含流忙碌的相关信息
      const responseStr = JSON.stringify(data);
      if (responseStr.includes('5020') || 
          responseStr.includes('RtcStreamBusy') || 
          responseStr.includes('stream already exists') || 
          responseStr.includes('stream busy') ||
          responseStr.includes('busy')) {
        errorMsg = `推流连接失败: 流 ${streamName} 已存在或忙碌，可能是重复推流。请先关闭现有连接后重试。`;
        console.warn('⚠️ [WebRTC] 流忙碌错误，可能需要先关闭现有连接');
      } else {
        // 400 错误但不确定原因，提供通用提示
        errorMsg = `推流连接失败: SRS 返回错误码 400。\n\n可能原因：\n1. 流已存在（重复推流）\n2. 参数格式错误\n3. 流名称冲突\n\n建议：关闭当前通话窗口，等待几秒后重新尝试`;
      }
    }
    
    console.error('❌ [WebRTC] 推流 SDP 交换失败:', {
      code: errorCode,
      message: errorMsg,
      fullResponse: data,
    });
    throw new Error(errorMsg);
  }

  if (!data.sdp) {
    console.error('❌ [WebRTC] 推流 SDP 交换失败: SRS 未返回 SDP answer');
    throw new Error('推流连接失败: SRS 未返回 SDP answer');
  }

  console.log('✅ [WebRTC] 推流 SDP 交换成功 (JSON 格式)');
  console.log('✅ [WebRTC] Answer SDP 长度:', data.sdp.length);
  console.log('✅ [WebRTC] Answer SDP 预览:', data.sdp.substring(0, 300));
  return data.sdp;
}

/**
 * 发送 SDP offer 到 SRS（拉流）
 */
export async function playFromSrs(
  streamName: string,
  offer: RTCSessionDescriptionInit
): Promise<string> {
  console.log('📥 [WebRTC] 开始拉流 SDP 交换');
  console.log('📥 [WebRTC] 流名称:', streamName);
  console.log('📥 [WebRTC] Offer 类型:', offer.type);
  console.log('📥 [WebRTC] Offer SDP 长度:', offer.sdp?.length || 0);
  console.log('📥 [WebRTC] Offer SDP 预览:', offer.sdp?.substring(0, 200) || 'N/A');
  
  const token = await getTokenAsync();
  if (!token) {
    throw new Error('请先登录');
  }

  // 前端只传递必要信息（streamName 和 sdp），由后端构建完整的 SRS 请求体
  // 后端会使用自己的 srs_config 来构建 api、streamurl、app 等字段
  console.log('📥 [WebRTC] 流名称:', streamName);
  console.log('📥 [WebRTC] 后端代理 URL:', getSrsApiUrl('/rtc/v1/play'));

  const requestBody: any = {
    stream: streamName,  // 只传递流名称，后端会构建其他字段
    sdp: offer.sdp,
  };

  const apiUrl = getSrsApiUrl('/rtc/v1/play')
  console.log('📥 [WebRTC] 请求体:', {
    stream: requestBody.stream,
    sdpLength: requestBody.sdp?.length || 0,
  });
  console.log('📥 [WebRTC] 准备发送请求到后端:', apiUrl);
  console.log('📥 [WebRTC] 请求方法: POST');
  console.log('📥 [WebRTC] 请求头: Authorization Bearer token');

  const response = await fetch(apiUrl, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
      'Authorization': `Bearer ${token}`,
    },
    body: JSON.stringify(requestBody),
  });

  console.log('📥 [WebRTC] 拉流响应状态:', response.status, response.statusText);
  console.log('📥 [WebRTC] 拉流响应头:', Object.fromEntries(response.headers.entries()));

  const responseText = await response.text();
  console.log('📥 [WebRTC] 拉流响应体长度:', responseText.length);
  console.log('📥 [WebRTC] 拉流响应体预览:', responseText.substring(0, 300));
  
  // 检查 HTTP 状态码
  if (!response.ok) {
    // 检查是否是流不存在错误（400/404），提供更详细的错误信息
    let errorMessage = `拉流请求失败: ${response.status} ${responseText}`;
    try {
      const errorDetail = JSON.parse(responseText);
      if (errorDetail.code === 400 || errorDetail.code === 404) {
        errorMessage = `拉流连接失败: 流 ${streamName} 不存在或尚未发布，请确保对方已接听通话`;
      } else if (errorDetail.message || errorDetail.msg) {
        errorMessage = `拉流连接失败: ${errorDetail.message || errorDetail.msg}`;
      }
    } catch (parseError) {
      // 如果不是 JSON 格式，检查文本内容
      if (responseText.includes('400') || responseText.includes('404') || 
          responseText.includes('stream not found') || responseText.includes('no stream')) {
        errorMessage = `拉流连接失败: 流 ${streamName} 不存在或尚未发布，请确保对方已接听通话`;
      }
    }
    
    throw new Error(errorMessage);
  }

  // 处理响应
  if (responseText.trim().startsWith('v=')) {
    // SDP 格式响应
    console.log('✅ [WebRTC] 拉流 SDP 交换成功 (SDP 格式)');
    console.log('✅ [WebRTC] Answer SDP 长度:', responseText.length);
    console.log('✅ [WebRTC] Answer SDP 预览:', responseText.substring(0, 300));
    return responseText;
  }

  // JSON 格式响应
  const data = JSON.parse(responseText);
  console.log('📥 [WebRTC] 拉流响应 JSON:', {
    code: data.code,
    message: data.message || data.msg,
    hasSdp: !!data.sdp,
    sdpLength: data.sdp?.length || 0,
  });
  
  if (data.code !== 0) {
    const errorCode = data.code;
    let errorMsg = data.message || data.msg || `SRS 返回错误码: ${errorCode}`;
    
    // 针对 400 错误提供更详细的提示
    if (errorCode === 400) {
      errorMsg = `拉流连接失败: 流 ${streamName} 不存在或尚未发布。\n\n可能原因：\n1. 对方尚未接听通话\n2. 对方的推流连接失败\n3. 流名称不正确\n\n请确保对方已接听通话，或稍后重试`;
    }
    
    console.error('❌ [WebRTC] 拉流 SDP 交换失败:', {
      code: errorCode,
      message: errorMsg,
      fullResponse: data,
    });
    throw new Error(`拉流连接失败: ${errorMsg}`);
  }

  if (!data.sdp) {
    console.error('❌ [WebRTC] 拉流 SDP 交换失败: SRS 未返回 SDP answer');
    throw new Error('拉流连接失败: SRS 未返回 SDP answer');
  }

  console.log('✅ [WebRTC] 拉流 SDP 交换成功 (JSON 格式)');
  console.log('✅ [WebRTC] Answer SDP 长度:', data.sdp.length);
  console.log('✅ [WebRTC] Answer SDP 预览:', data.sdp.substring(0, 300));
  return data.sdp;
}

/**
 * 查询流的播放者数量（用于判断对方是否接听）
 */
export async function checkStreamPlayers(streamName: string): Promise<{ player_count: number; has_players: boolean }> {
  console.log('🔍 [WebRTC] 查询流的播放者数量:', streamName);
  
  const token = await getTokenAsync();
  if (!token) {
    throw new Error('请先登录');
  }

  const apiUrl = `${getSrsApiUrl('/stream/players')}?stream=${encodeURIComponent(streamName)}`;
  console.log('🔍 [WebRTC] 查询播放者 API URL:', apiUrl);

  const response = await fetch(apiUrl, {
    method: 'GET',
    headers: {
      'Accept': 'application/json',
      'Authorization': `Bearer ${token}`,
    },
  });

  console.log('🔍 [WebRTC] 查询播放者响应状态:', response.status, response.statusText);

  if (!response.ok) {
    const errorText = await response.text();
    console.error('🔍 [WebRTC] 查询播放者失败:', errorText);
    throw new Error(`查询播放者失败: ${response.status} ${errorText}`);
  }

  const data = await response.json();
  console.log('🔍 [WebRTC] 查询播放者响应:', data);

  if (data.code === 0 && data.data) {
    return {
      player_count: data.data.player_count || 0,
      has_players: data.data.has_players || false,
    };
  }

  throw new Error(data.message || '查询播放者失败');
}

